import originAxios from 'axios'
import { TOKEN_KEY } from '@/utils/constants'
import { cacheUrls } from '@/utils/constants/urls'
import { tip } from '@tip'

let cacheData = {}
const create = function (options) {
  const axios = originAxios.create(options)
  axios.interceptors.request.use(function (config) {
    const appToken = localStorage.getItem(TOKEN_KEY)
    if (appToken) {
      config.headers['authorization'] = appToken
    }
    return config
  })
  axios.interceptors.response.use(function (response) {
    if (response.config.responseType === 'blob') {
      return response
    } else {
      return response.data
    }
  })
  return axios
}

export const hostApi = 'http://localhost:9000/api'

const axios = create({
  baseURL: hostApi,
  withCredentials: true,
})
const request = function (url, data = {}, config = {}) {
  if (!url) {
    throw new Error('请确认请求的url存在！')
  }
  // 自定义的配置项都以 _ 开头
  // 是否显示成功后的提示，默认值为true
  const showSuccessTip = config._showSuccessTip !== false
  // 是否显示失败后的提示，默认值为true
  const showErrorTip = config._showErrorTip !== false
  // 是否批量trim，默认值为true
  const isTrim = config._isTrim !== false
  // 是否返回原始数据 默认为 false
  const isReturnOrigin = config._isReturnOrigin === true
  if (isTrim) {
    deepTrim(data)
  }
  // 是否强制不使用缓存，默认为false，即默认根据缓存配置使用缓存
  const forceWithoutCache = config._forceWithoutCache === true
  // 如果使用缓存
  if (!forceWithoutCache) {
    // 如果存在缓存
    const cacheRes = getCacheData({ url, data })
    if (cacheRes) {
      return cacheRes
    }
  }
  return new Promise((resolve, reject) => {
    axios({
      url,
      ...config,
      ...(config.method === 'get' ? { params: data } : { data }),
    })
      .then((res) => {
        if (typeof res === 'string' || config.responseType === 'blob' || isReturnOrigin) {
          resolve(res)
          return
        }
        const message = res.message
        if (res.code === 200) {
          const resData = {
            data: res.data,
            ...('total' in res ? { total: res.total } : {}),
          }
          // 如果需要使用缓存
          if (!forceWithoutCache && cacheUrls.includes(url)) {
            cacheData = {
              ...cacheData,
              [getCacheDataKey({ url, data })]: new Promise((re) => {
                re(resData)
              }),
            }
          }
          resolve(resData)
          if (showSuccessTip && message && message !== 'ok') {
            tip({ message, type: 'success' })
          }
        } else {
          if (showErrorTip && message && message !== 'ok') {
            tip({ message, type: 'error' })
          }
          reject()
        }
      })
      .catch((e) => {
        const code = e.response?.data?.code
        const message = e.response?.data?.message
        if (showErrorTip && message && message !== 'ok') {
          tip({ message, type: 'error' })
        }
        if (code === 403) {
          // token已过期，跳转到登录界面
          if (!window.location.href.includes('/login')) {
            window.location.href = '/login'
          }
        } else {
          // resolve(e.response?.data)
          reject()
        }
      })
  })
}
const req = {
  get(url, data = {}, config = {}) {
    return request(url, data, {
      ...config,
      method: 'get',
    })
  },
  post(url, data = {}, config = {}) {
    return request(url, data, {
      ...config,
      method: 'post',
    })
  },
  put(url, data = {}, config = {}) {
    return request(url, data, {
      ...config,
      method: 'put',
    })
  },
  delete(url, data = {}, config = {}) {
    return request(url, data, {
      ...config,
      method: 'delete',
    })
  },
}
export default req

function isObj(obj) {
  return obj != null && typeof obj === 'object'
}

function isString(obj) {
  return typeof obj === 'string'
}

function isArray(obj) {
  return Array.isArray(obj)
}

function isArrayOrObj(obj) {
  return isObj(obj) || isArray(obj)
}

function deepTrim(data) {
  if (Array.isArray(data)) {
    data.forEach((item, i) => {
      if (isArrayOrObj(item)) {
        deepTrim(item)
      } else {
        if (isString(item)) {
          data[i] = item.trim()
        }
      }
    })
  } else {
    if (isObj(data)) {
      Object.keys(data).forEach((key) => {
        if (isString(data[key])) {
          data[key] = data[key].trim()
        } else if (isArrayOrObj(data[key])) {
          deepTrim(data[key])
        }
      })
    }
  }
}

function isEmptyObj(data) {
  return Object.keys(data).length === 0
}

function getCacheDataKey({ url, data }) {
  return `${url}${isEmptyObj(data) ? '' : `__${JSON.stringify(data)}`}`
}

function getCacheData({ url, data }) {
  return cacheData[getCacheDataKey({ url, data })]
}

export function delCacheData(delConfig = undefined) {
  // 删除所有的缓存
  if (delConfig) {
    cacheData = {}
    return
  }
  // 删除指定的缓存，若只传url，则删除url对应的所有缓存，若url和data都传，则删除对应的特定缓存
  const key = getCacheDataKey(delConfig)
  Object.keys(cacheData).forEach((k) => {
    if (k === key || k.startsWith(`${key}__`)) {
      delete cacheData[k]
    }
  })
}
